unit iconselection;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ButtonPanel, StdCtrls,
  ExtCtrls, Spin, LCLTranslator;

type

  { TIconSelectionForm }

  TIconSelectionForm = class(TForm)
    IconIdLabel: TLabel;
    ManualSettingPanel: TPanel;
    IconsetPaintBox: TPaintBox;
    ResultButtonPanel: TButtonPanel;
    IconIdSpinEdit: TSpinEdit;
    IconsetScrollBox: TScrollBox;
    procedure CancelButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure IconIdSpinEditChange(Sender: TObject);
    procedure IconsetPaintBoxDblClick(Sender: TObject);
    procedure IconsetPaintBoxMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure IconsetPaintBoxPaint(Sender: TObject);
    procedure OKButtonClick(Sender: TObject);
    procedure ResultButtonPanelKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    ResultWasAccepted: Boolean;
  public
    SelectedIconId: Integer;
    function ShowIconSelection(AId: Integer = 0): Boolean;
  end;

var
  IconSelectionForm: TIconSelectionForm;

implementation

uses
  globals, LCLType;

{$R *.lfm}

{ TIconSelectionForm }

procedure TIconSelectionForm.FormCreate(Sender: TObject);
begin
  SelectedIconId := 0;
end;

procedure TIconSelectionForm.CancelButtonClick(Sender: TObject);
begin
  ResultWasAccepted := False;
  Close
end;

procedure TIconSelectionForm.FormShow(Sender: TObject);
begin
  if Game.IconGraphics <> nil then begin
    IconsetPaintBox.Width := Game.IconGraphics.Width;
    IconsetPaintBox.Height := Game.IconGraphics.Height;
  end else begin
    IconsetPaintBox.Width := 1;
    IconsetPaintBox.Height := 1;
  end;

  (* Its position can be reset by FlipChildren (for RTL languages) which results
     in parts of the iconset being hidden. So, reset it. It should in theory
     be right-aligned but I had problems with determining the scrollbar width,
     so this will do. *)
  IconsetPaintBox.Left := 0
end;

procedure TIconSelectionForm.IconIdSpinEditChange(Sender: TObject);
begin
  SelectedIconId := IconIdSpinEdit.Value;
  IconsetPaintBox.Refresh;
end;

procedure TIconSelectionForm.IconsetPaintBoxDblClick(Sender: TObject);
begin
  (* This causes problems on Windows: if you close the window by double-click,
  subsequent calls to show ImageSelectionForm will not show anything.
  I don't know what causes this, so let's keep it commented out for a while. *)
  {$IF not Defined(LCLWin32)}
  ResultWasAccepted := True;
  Close
  {$ENDIF}
end;

procedure TIconSelectionForm.IconsetPaintBoxMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  IconRow, IconCol: Integer;
begin
  IconRow := Y div 32; //TODO: allow icons of different sizes
  IconCol := X div 32;

  SelectedIconId := (IconRow * 16) + IconCol;
  IconIdSpinEdit.Value := SelectedIconId;
  IconsetPaintBox.Refresh;
end;

procedure TIconSelectionForm.IconsetPaintBoxPaint(Sender: TObject);
var
  SelectionRect: TRect;
  IconsPerLine: Integer = 16; //TODO: allow other icon sizes
begin
  if Game.IconGraphics = nil then
    Exit;

  IconsetPaintBox.Canvas.Draw(0, 0, Game.IconGraphics);
  with SelectionRect do begin
    Left := (SelectedIconId mod IconsPerLine) * 32; //TODO: allow other icon sizes
    Top := (SelectedIconId div IconsPerLine) * 32;
    Right := Left + 32;
    Bottom := Top + 32;
  end;

  with IconsetPaintBox.Canvas do begin
    Brush.Style := bsClear;
    Pen.Color := clWhite;
    Pen.Width := 2;
    Rectangle(SelectionRect);

    Pen.Color := clBlack;
    SelectionRect.Inflate(-2, -2, -2, -2);
    Rectangle(SelectionRect);

    Pen.Color := clWhite;
    SelectionRect.Inflate(-2, -2, -2, -2);
    Rectangle(SelectionRect);
  end;
end;

procedure TIconSelectionForm.OKButtonClick(Sender: TObject);
begin
  ResultWasAccepted := True;
  Close
end;

procedure TIconSelectionForm.ResultButtonPanelKeyDown(Sender: TObject;
  var Key: Word; Shift: TShiftState);
begin
  case Key of
    VK_LEFT:
      Dec(SelectedIconId, 1);
    VK_RIGHT:
      Inc(SelectedIconId, 1);
    VK_UP:
      Dec(SelectedIconId, 16);
    VK_DOWN:
      Inc(SelectedIconId, 16);
    VK_RETURN:
      if IconsetScrollBox.Focused then begin
        ResultWasAccepted := True;
        Close
      end;
    VK_ESCAPE: begin
      ResultWasAccepted := False;
      Close
    end;
  end;

  IconIdSpinEdit.Value := SelectedIconId;
end;

function TIconSelectionForm.ShowIconSelection(AId: Integer): Boolean;
begin
  ResultWasAccepted := False;
  SelectedIconId := AId;
  IconIdSpinEdit.Value := AId;

  ShowModal;

  ShowIconSelection := ResultWasAccepted;
end;

end.

